using Castle.DynamicProxy;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Thrift.Protocol;
using Thrift.Transport;

namespace Thrift.Utility
{
    public class ThriftClient2<T> : IDisposable where T : class
    {
        private string serviceName;

        private TTransport transport;

        private T instance;        

        private bool disposed;

        public ThriftClient2(string serviceName=null)
        {
            disposed = false;
            
            Type interfaceType = typeof(T);
            if (string.IsNullOrWhiteSpace(serviceName))
            {
                this.serviceName = interfaceType.FullName;
                if (this.serviceName.LastIndexOf(".") != -1)
                {
                    this.serviceName = this.serviceName.Substring(0, this.serviceName.LastIndexOf("."));
                }
                if (this.serviceName.LastIndexOf("+") != -1)
                {
                    this.serviceName = this.serviceName.Substring(0, this.serviceName.LastIndexOf("+"));
                }
            }
            else
            {
                this.serviceName = serviceName;
            }

            transport = ThriftFactory.BorrowInstance(this.serviceName);                       
            
            var config = (from c in ConfigHelper.GetServiceConfigs() where c.Name == this.serviceName select c).FirstOrDefault();
            if (config == null)
            {
                throw new ThriftException(string.Format("There Is No Service Named \"{0}\"", serviceName));
            }

            TProtocol protocol = new TBinaryProtocol(transport);
            if (config.ProtocolType.ToLower() == "json")
            {
                protocol = new TJSONProtocol(transport);
            }

            Type type = Type.GetType(config.ServiceType);
            T client = (T)Activator.CreateInstance(type, protocol);

            if(config.IsMuiltiple.ToLower()=="true")
            {
                TMultiplexedProtocol mProtocol = new TMultiplexedProtocol(protocol, this.serviceName);
                client = (T)Activator.CreateInstance(type, mProtocol);
            }

            var generator = new ProxyGenerator();
            instance = (T)generator.CreateInterfaceProxyWithTarget(interfaceType, client, new ProxyInterceptor());
        }

        public T Instance
        {
            get { return instance; }
        }

        ~ThriftClient2()
        {
            Dispose(false);
        }

        protected void Dispose(bool disposing)
        {
            if (!disposed)
            {
                if (disposing)
                {
                    ThriftFactory.ReturnInstance(serviceName, transport);
                }
                disposed = true;
            }
        }
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
    }
}